Make xen daemon startup more robust.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 10 Aug 2005 09:46:51 +0000 (09:46 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 10 Aug 2005 09:46:51 +0000 (09:46 +0000)
1) make xenconsoled exit gracefully if xcs dies
2) daemonize xenstored before binding to xenstored socket
3) wait to close stdio in xenstored until we're ready to accept
connections (so that PID=`xenstored --output-pid` doesn't return until
it's ready to accept connections)
4) updates tools/misc/xend for these changes
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustycorp.com.au>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
tools/console/daemon/io.c
tools/console/daemon/utils.c
tools/misc/xend
tools/xenstore/utils.c
tools/xenstore/utils.h
tools/xenstore/xenstored_core.c

index 364245f019c0f042309f8e12c625378df51d406b..87c3cc06e618b47d8993334a3106bf341522eef4 100644 (file)
@@ -231,6 +231,7 @@ static void handle_tty_read(struct domain *dom)
 
                if (!write_sync(xcs_data_fd, &msg, sizeof(msg))) {
                        dolog(LOG_ERR, "Write to xcs failed: %m");
+                       exit(1);
                }
        } else {
                close(dom->tty_fd);
@@ -262,6 +263,7 @@ static void handle_xcs_msg(int fd)
 
        if (!read_sync(fd, &msg, sizeof(msg))) {
                dolog(LOG_ERR, "read from xcs failed! %m");
+               exit(1);
        } else if (msg.type == XCS_REQUEST) {
                struct domain *dom;
 
index 6bc7cfd3a5978af81ea53b0bdf2a588bc693c6dd..96f823bdc704cbd0893e7e0763b471c34748e4ed 100644 (file)
@@ -59,6 +59,8 @@ bool _read_write_sync(int fd, void *data, size_t size, bool do_read)
 
                if (len < 1) {
                        if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
+                               continue;
+                       } else {
                                return false;
                        }
                } else {
index 80a4f00ced34872f4b8e0bfdb8c0ba181c651d91..5abcdc6e0465692fb9936ffe9915faf0117baddb 100644 (file)
@@ -24,6 +24,7 @@ import sys
 import socket
 import signal
 import time
+import commands
 
 XCS_PATH    = "/var/lib/xen/xcs_socket"
 XCS_EXEC    = "/usr/sbin/xcs"
@@ -116,8 +117,7 @@ def stop_xcs():
        return    
 
 def start_xenstored():
-    if os.fork() == 0:
-        os.execvp('/usr/sbin/xenstored', ['/usr/sbin/xenstored']);
+    s,o = commands.getstatusoutput("/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid");
 
 def start_consoled():
     if os.fork() == 0:
index 0b1ac8aedd77802d758744fe17ef8e59bc46cbd4..2bc40e009b3079324503c6d3e0c26a46839103c9 100644 (file)
@@ -80,30 +80,6 @@ void *malloc_nofail(size_t size)
        barf("malloc of %zu failed", size);
 }
 
-/* Stevens. */
-void daemonize(void)
-{
-       pid_t pid;
-
-       /* Separate from our parent via fork, so init inherits us. */
-       if ((pid = fork()) < 0)
-               barf_perror("Failed to fork daemon");
-       if (pid != 0)
-               exit(0);
-
-       close(STDIN_FILENO);
-       close(STDOUT_FILENO);
-       close(STDERR_FILENO);
-
-       /* Session leader so ^C doesn't whack us. */
-       setsid();
-       /* Move off any mount points we might be in. */
-       chdir("/");
-       /* Discard our parent's old-fashioned umask prejudices. */
-       umask(0);
-}
-
-
 /* This version adds one byte (for nul term) */
 void *grab_file(const char *filename, unsigned long *size)
 {
index a84f19a22af9baebbc357d5e98d434844b167a70..5fbfceeaa915d5a8426b9341ab01da6c7eb79c45 100644 (file)
@@ -40,9 +40,6 @@ void barf_perror(const char *fmt, ...) __attribute__((noreturn));
 void *grab_file(const char *filename, unsigned long *size);
 void release_file(void *data, unsigned long size);
 
-/* For writing daemons, based on Stevens. */
-void daemonize(void);
-
 /* Signal handling: returns fd to listen on. */
 int signal_to_fd(int signal);
 void close_signal(int fd);
index 40fc8a7942fc0d8ec0800ecde8e1965829f25045..c91021876bc91ed9f72b9a1ce465f0aafa83bfd5 100644 (file)
@@ -1540,10 +1540,49 @@ static void setup_structure(void)
                            xs_daemon_transactions());
 }
 
+static void write_pidfile(const char *pidfile)
+{
+       char buf[100];
+       int len;
+       int fd;
+
+       fd = open(pidfile, O_RDWR | O_CREAT, 0600);
+       if (fd == -1)
+               barf_perror("Opening pid file %s", pidfile);
+
+       /* We exit silently if daemon already running. */
+       if (lockf(fd, F_TLOCK, 0) == -1)
+               exit(0);
+
+       len = sprintf(buf, "%d\n", getpid());
+       write(fd, buf, len);
+}
+
+/* Stevens. */
+static void daemonize(void)
+{
+       pid_t pid;
+
+       /* Separate from our parent via fork, so init inherits us. */
+       if ((pid = fork()) < 0)
+               barf_perror("Failed to fork daemon");
+       if (pid != 0)
+               exit(0);
+
+       /* Session leader so ^C doesn't whack us. */
+       setsid();
+       /* Move off any mount points we might be in. */
+       chdir("/");
+       /* Discard our parent's old-fashioned umask prejudices. */
+       umask(0);
+}
+
+
 static struct option options[] = { { "no-fork", 0, NULL, 'N' },
                                   { "verbose", 0, NULL, 'V' },
                                   { "output-pid", 0, NULL, 'P' },
                                   { "trace-file", 1, NULL, 'T' },
+                                  { "pid-file", 1, NULL, 'F' },
                                   { NULL, 0, NULL, 0 } };
 
 int main(int argc, char *argv[])
@@ -1553,6 +1592,7 @@ int main(int argc, char *argv[])
        fd_set inset, outset;
        bool dofork = true;
        bool outputpid = false;
+       const char *pidfile = NULL;
 
        while ((opt = getopt_long(argc, argv, "DVT:", options, NULL)) != -1) {
                switch (opt) {
@@ -1572,11 +1612,20 @@ int main(int argc, char *argv[])
                                            optarg);
                         write(tracefd, "\n***\n", strlen("\n***\n"));
                        break;
+               case 'F':
+                       pidfile = optarg;
                }
        }
        if (optind != argc)
                barf("%s: No arguments desired", argv[0]);
 
+       if (dofork) {
+               openlog("xenstored", 0, LOG_DAEMON);
+               daemonize();
+       }
+       if (pidfile)
+               write_pidfile(pidfile);
+
        talloc_enable_leak_report_full();
 
        /* Create sockets for them to listen to. */
@@ -1623,19 +1672,18 @@ int main(int argc, char *argv[])
        /* Restore existing connections. */
        restore_existing_connections();
 
-       /* Debugging: daemonize() closes standard fds, so dup here. */
-       tmpout = dup(STDOUT_FILENO);
-       if (dofork) {
-               openlog("xenstored", 0, LOG_DAEMON);
-               daemonize();
-       }
-
        if (outputpid) {
                char buffer[20];
                sprintf(buffer, "%i\n", getpid());
                write(tmpout, buffer, strlen(buffer));
        }
-       close(tmpout);
+
+       /* close stdin/stdout now we're ready to accept connections */
+       if (dofork) {
+               close(STDIN_FILENO);
+               close(STDOUT_FILENO);
+               close(STDERR_FILENO);
+       }
 
 #ifdef TESTING
        signal(SIGUSR1, stop_failtest);